package com.liujit.generator.service;

import cn.hutool.core.util.StrUtil;
import com.liujit.common.utils.DozerConvertor;
import com.liujit.generator.config.DataSourceConfig;
import com.liujit.generator.domain.model.FieldInfo;
import com.liujit.generator.domain.model.TableInfo;
import com.liujit.generator.domain.model.TemplateInfo;
import com.liujit.generator.domain.param.GeneratorParam;
import com.liujit.generator.engine.TemplateEngine;
import com.liujit.generator.engine.base.AbstractTemplateEngine;
import com.liujit.generator.engine.config.ContextConfig;
import com.liujit.generator.enums.DbColumnType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 表工具类
 * @Author LiuJun
 * @Date 2020/8/14 9:51 上午
 */
@Slf4j
@Service
@EnableConfigurationProperties({ DataSourceConfig.class })
public class GeneratorService {

    private DataSourceConfig dataSourceConfig;

    public GeneratorService(DataSourceConfig dataSourceConfig) {
        this.dataSourceConfig = dataSourceConfig;
    }

    private TemplateInfo create(String name, String comment) {
        TemplateInfo template = new TemplateInfo();
        template.setName(name);
        template.setComment(comment);
        return template;
    }

    /**
     * 获取模板内容
     *
     * @return
     */
    public List<TemplateInfo> getTemplateInfo() {
        List<TemplateInfo> templateInfos = new ArrayList<>();
        templateInfos.add(this.create("controllerSwitch", "controller-模板"));
        templateInfos.add(this.create("serviceSwitch", "service-模板"));
        templateInfos.add(this.create("mapperSwitch", "mapper-模板"));
        templateInfos.add(this.create("modelSwitch", "model-模板"));
        templateInfos.add(this.create("querySwitch", "query-模板"));
        templateInfos.add(this.create("paramsSwitch", "param-模板"));
        return templateInfos;
    }

    /**
     * 查询数据库表信息
     *
     * @param projectName
     * @return
     */
    public List<TableInfo> getTableInfo(String projectName) {
        // 获取数据库连接，查询表结构信息
        Connection conn = dataSourceConfig.getConn(projectName);
        Statement sm = null;
        List<TableInfo> tables = new ArrayList<>();
        try {
            sm = conn.createStatement();
            String sql = "select table_name,table_comment from information_schema.`tables` where table_schema = (select database()) order by table_name desc";
            log.info(sql);
            ResultSet rs = sm.executeQuery(sql);
            while (rs.next()) {
                TableInfo table = new TableInfo();
                table.setName(rs.getString(1));
                table.setComment(rs.getString(2));
                table.setLabel(table.getName() + "-" + table.getComment());
                tables.add(table);
            }
        } catch (SQLException e) {
            log.error(e.getMessage());
        }
        if (sm != null) {
            try {
                sm.close();
            } catch (SQLException e) {
                log.error(e.getMessage());
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                log.error(e.getMessage());
            }
        }
        return tables;
    }

    /**
     * 代码生成
     *
     * @param param
     */
    public void generate(GeneratorParam param) {
        AbstractTemplateEngine templateEngine = new TemplateEngine();
        // 全局配置设置
        ContextConfig contextConfig = DozerConvertor.convertor(param, ContextConfig.class);
        templateEngine.setContextConfig(contextConfig);
        // 表字段信息获取
        List<FieldInfo> fieldInfos = this.getFieldInfo(param.getProjectName(), param.getTableName());
        templateEngine.setFieldInfos(fieldInfos);
        // 判断字段信息
        // 包含enabled
        Boolean enabled = false;
        // 包含createTime
        Boolean createTime = false;
        // 包含Date
        Boolean date = false;
        // 包含BigDecimal
        Boolean bigDecimal = false;
        for (FieldInfo fieldInfo : fieldInfos) {
            String name = fieldInfo.getName();
            if ("enabled".equals(name)) {
                if (!enabled) {
                    enabled = true;
                }
            } else if ("create_time".equals(name) || "update_time".equals(name)) {
                if (!createTime) {
                    createTime = true;
                }
            } else {
                String type = fieldInfo.getType();
                if (!date && "Date".equals(type)) {
                    date = true;
                }
                if (!bigDecimal && "BigDecimal".equals(type)) {
                    bigDecimal = true;
                }
            }
        }
        templateEngine.setEnabled(enabled);
        templateEngine.setCreateTime(createTime);
        templateEngine.setDate(date);
        templateEngine.setBigDecimal(bigDecimal);
        templateEngine.start();
    }

    /**
     * 查询表结构信息
     *
     * @param projectName
     * @param tableName
     * @return
     */
    private List<FieldInfo> getFieldInfo(String projectName, String tableName) {
        Connection conn = dataSourceConfig.getConn(projectName);
        Statement sm = null;
        List<FieldInfo> fieldInfos = new ArrayList<>();
        try {
            sm = conn.createStatement();
            String sql =
                    "select column_name, data_type, column_comment, character_maximum_length from information_schema.columns where table_schema = (select database()) and table_name = '"
                            + tableName + "'";
            log.info(sql);
            ResultSet rs = sm.executeQuery(sql);
            while (rs.next()) {
                FieldInfo fieldInfo = new FieldInfo();
                fieldInfo.setName(rs.getString(1));
                DbColumnType column = DbColumnType.get(rs.getString(2));
                fieldInfo.setType(column.getType());
                fieldInfo.setComment(rs.getString(3));
                fieldInfo.setPropertyName(StrUtil.toCamelCase(fieldInfo.getName()));
                fieldInfo.setLen(rs.getLong(4));
                fieldInfos.add(fieldInfo);
            }
        } catch (SQLException e) {
            log.error(e.getMessage());
        }
        if (sm != null) {
            try {
                sm.close();
            } catch (SQLException e) {
                log.error(e.getMessage());
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                log.error(e.getMessage());
            }
        }
        return fieldInfos;
    }
}
